using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Build.Evaluation;

namespace Templates
{
	public static class ProjectFactory
	{
		static ProjectFactory()
		{
			CurrentEncoding = Encoding.UTF8;
		}

		private static Encoding _currentEncoding;
		public static Encoding CurrentEncoding
		{
			get { return _currentEncoding; }
			set
			{
				if ((value != null))
				{
					_currentEncoding = value;
				}
			}
		}

		private static void Write(Stream stream, string str)
		{
			byte[] bytes = CurrentEncoding.GetBytesWithSignature(str);
			stream.Write(bytes, 0, bytes.Length);
		}



		public static void Write(string fileName, string content, bool useProject = false, ProjectFileType prjFileType = ProjectFileType.Compile)
		{
			if (useProject && string.IsNullOrWhiteSpace(ProjectPath))
				throw new ApplicationException("Uknown Project");

			if (useProject)
				fileName = new FileInfo(Path.Combine(ProjectPath, fileName)).FullName;

			using (FileStream sw = new FileStream(fileName, FileMode.Create))
			{
				Write(sw, content);
			}

			if (useProject)
			{
				Project prj = ProjectCollection
					.GlobalProjectCollection
					.LoadedProjects
					.SingleOrDefault(x => x.FullPath.ToLower() == ProjectFullName.ToLower())
					?? new Project(ProjectFullName);

				string prjFileTypeStr = prjFileType.ToString();
				if (!prj.GetItems(prjFileTypeStr).Any(x => x.EvaluatedInclude == fileName))
				{
					prj.AddItem(prjFileTypeStr, fileName);
					prj.Save();
				}

				ProjectCollection.GlobalProjectCollection.UnloadProject(prj);
			}

		}

		public static string ProjectFullName { get; set; }

		private static string ProjectPath
		{
			get
			{
				if (ProjectFullName == null)
					return null;
				return new FileInfo(ProjectFullName).Directory.FullName;
			}
		}

/*
		public static void Test()
		{
			FileInfo projFileInfo = new FileInfo(codeFile.ProjFullName);
			DirectoryInfo directoryInfo;

			if (projFileInfo.Exists)
			{
				Project prj = ProjectCollection
					.GlobalProjectCollection
					.LoadedProjects
					.SingleOrDefault(x => x.FullPath.ToLower() == codeFile.ProjFullName.ToLower())
					?? new Project(codeFile.ProjFullName);

				if (!prj.GetItems(codeFile.ProjectFileType).Any(x => x.EvaluatedInclude == codeFile.ProjectFilePath))
				{
					prj.AddItem(codeFile.ProjectFileType, codeFile.ProjectFilePath);
					prj.Save();
					messages.Add(string.Format("<b>\"{0}\" add to project \"{1}\"</b>", codeFile.ProjectFilePath,
																		 codeFile.ProjFullName));
				}
				else
				{
					messages.Add(string.Format("\"{0}\" exist into project \"{1}\"", codeFile.ProjectFilePath, codeFile.ProjFullName));
				}
				ProjectCollection.GlobalProjectCollection.UnloadProject(prj);

				directoryInfo = projFileInfo.Directory;
			}
			else
			{
				messages.Add(string.Format("<span class=\"red\">Project \"{0}\" doesn't exist</span>", codeFile.ProjFullName));
				directoryInfo = new DirectoryInfo(codeFile.ProjFullName);
				if (!directoryInfo.Exists)
				{
					directoryInfo.Create();
					messages.Add(string.Format("<b>Directory \"{0}\" create</b>", directoryInfo));
				}
				else
				{
					messages.Add(string.Format("Directory \"{0}\" exist", directoryInfo));
				}
			}

			FileInfo generatedFile = new FileInfo(Path.Combine(directoryInfo.FullName, codeFile.ProjectFilePath));

			DirectoryInfo generatedDirectory = generatedFile.Directory;
			if (!generatedDirectory.Exists)
			{
				generatedDirectory.Create();
				messages.Add(string.Format("<b>Directory \"{0}\" create</b>", generatedDirectory.FullName));
			}
			else
			{
				messages.Add(string.Format("Directory \"{0}\" exist", generatedDirectory.FullName));
			}

			using (FileStream sw = new FileStream(generatedFile.FullName, FileMode.Create))
			{
				//var utf8 = new UTF8Encoding(false);
				//var bytes = utf8.GetBytes(codeFile.TransformText());
				var bytes = Encoding.UTF8.GetBytes(codeFile.TransformText());
				bytes = Encoding.UTF8.GetPreamble().Concat(bytes).ToArray();

				sw.Write(bytes, 0, bytes.Length);
				messages.Add(string.Format("<b>File \"{0}\" generated</b>", generatedFile.FullName));
			}
		}
*/
	}

	internal static class EncodingExtention
	{
		internal static byte[] GetBytesWithSignature(this Encoding encoding, string text)
		{
			var bytes = encoding.GetBytes(text);
			return encoding.GetPreamble().Concat(bytes).ToArray();
		}
	}

	public enum ProjectFileType
	{
		Compile,
		Content
	}
}